#include "expression.h"
#include <stdio.h>

namespace syntax_analysis
{
	
	exp_opd::exp_opd()
	{
		m_type = OPD_RAW;
		m_opd_int = UNKNOWN;
		m_opd_exp = NULL;
	}
	
	exp_opd::exp_opd( int opd )
	{
		m_opd_int = opd;
		m_type = OPD_RAW;
		m_opd_exp = NULL;
	}
	
	exp_opd::exp_opd( expression *opd )
	{
		m_opd_exp = opd;
		m_type = OPD_EXPRESSION;
		m_opd_int = UNKNOWN;
	}

	exp_opd::~exp_opd()
	{
		if( m_opd_exp != NULL )
			delete m_opd_exp;
		m_type = OPD_RAW;
		m_opd_int = UNKNOWN;
		m_opd_exp = NULL;
	}
	
	int exp_opd::get_value()
	{
		int result = UNKNOWN;
		
		switch( m_type )
		{
		case OPD_RAW:
			result = m_opd_int;
			break;
		case OPD_EXPRESSION:
			result = m_opd_exp->get_value();
			break;
		}
		return result;
	}

	void exp_opd::set_opd( int opd )
	{
		m_opd_int = opd;
		m_type = OPD_RAW;
	}

	void exp_opd::set_opd( expression *opd )
	{
		if( m_opd_exp != NULL )
			delete m_opd_exp;
		m_opd_exp = opd;
		m_type = OPD_EXPRESSION;
	}
	
	expression::expression()
	{
		m_opt = OPT_ADD;
		m_opd1 = NULL;
		m_opd2 = NULL;
	}
	
	expression::expression( exp_opt opt, exp_opd *opd1, exp_opd *opd2 )
	{
		m_opt = opt;
		m_opd1 = opd1;
		m_opd2 = opd2;
	}
	
	expression::~expression( )
	{
		if( m_opd1 != NULL )
			delete m_opd1;
		if( m_opd2 != NULL )
			delete m_opd2;
		m_opt = OPT_ADD;
		m_opd1 = NULL;
		m_opd2 = NULL;
	}
	
	int expression::get_value()
	{
		int result = UNKNOWN;
		
		if( m_opt == OPT_NONE && m_opd1 != NULL )
			result = m_opd1->get_value();

		if( m_opd1 != NULL && m_opd2 != NULL )
		{
			switch( m_opt )
			{
			case OPT_ADD:
				result = m_opd1->get_value() + m_opd2->get_value();
				break;
			case OPT_SUB:
				result = m_opd1->get_value() - m_opd2->get_value();
				break;
			case OPT_MUL:
				result = m_opd1->get_value() * m_opd2->get_value();
				break;
			case OPT_DIV:
				result = m_opd1->get_value() / m_opd2->get_value();
				break;
			case OPT_MOD:
				result = m_opd1->get_value() % m_opd2->get_value();
				break;
			}
		}
		return result;
	}
	
	void expression::set_opt( exp_opt opt )
	{
		m_opt = opt;
	}
	
	void expression::set_opd1( exp_opd *opd )
	{
		m_opd1 = opd;
	}
	
	void expression::set_opd2( exp_opd *opd )
	{
		m_opd2 = opd;
	}
	
}